package alps.common.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
import android.widget.Toast;

import alps.common.R;

/**
 * 圆角矩形图片，可以指定任意圆角半径 <br>
 *  rri_radius:全部圆角半径 <br>
 *  rri_leftTopRadius:左上圆角半径 <br>
 *  rri_leftBottomRadius:左下圆角半径 <br>
 *  rri_rightTopRadius:右上圆角半径 <br>
 *  rri_rightBottomRadius:右下圆角半径 <br>
 *
 *  如指定了 rri_radius，则四圆角半径均设为该值，并不再响应其它属性设置<br>
 *
 * Created by alps on 2017/02/23.
 */
public class RoundRectImageView extends ImageView {

    /** 左上角序号 */
    public static final int LEFT_TOP_INDEX = 0;

    /** 右上角序号 */
    public static final int RIGHT_TOP_INDEX = 1;

    /** 右下角序号 */
    public static final int RIGHT_BOTTOM_INDEX = 2;

    /** 左下角序号 */
    public static final int LEFT_BOTTOM_INDEX = 3;

    /** 全部角序号 */
    public static final int ALL_INDEX = -1;

    private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
    private static final int COLORDRAWABLE_DIMENSION = 2;

    private final RectF mDrawableRect = new RectF();

    private final Matrix mShaderMatrix = new Matrix();
    private final Paint mBitmapPaint = new Paint();

    private Bitmap mBitmap;
    private BitmapShader mBitmapShader;
    private int mBitmapWidth;
    private int mBitmapHeight;

    private ColorFilter mColorFilter;

    private boolean mReady;
    private boolean mSetupPending;

    private float[] radii = new float[8];

    public RoundRectImageView(Context context) {
        super(context);

        init();
    }

    public RoundRectImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundRectImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundRectImageView, defStyle, 0);

        float leftTopRadius = a.getDimensionPixelSize(R.styleable.RoundRectImageView_rri_leftTopRadius, 0);
        float leftBottomRadius = a.getDimensionPixelSize(R.styleable.RoundRectImageView_rri_leftBottomRadius, 0);
        float rightBottomRadius = a.getDimensionPixelSize(R.styleable.RoundRectImageView_rri_rightBottomRadius, 0);
        float rightTopRadius = a.getDimensionPixelSize(R.styleable.RoundRectImageView_rri_rightTopRadius, 0);
        float radius = a.getDimensionPixelSize(R.styleable.RoundRectImageView_rri_radius, -1);

        if (radius >= 0) {
            setRadius(ALL_INDEX, radius, false);
        } else {
            setRadius(LEFT_TOP_INDEX, leftTopRadius, false);
            setRadius(RIGHT_TOP_INDEX, rightTopRadius, false);
            setRadius(RIGHT_BOTTOM_INDEX, rightBottomRadius, false);
            setRadius(LEFT_BOTTOM_INDEX, leftBottomRadius, false);
        }

        a.recycle();
        init();
    }

    /**
     * @param index         指定角，从左上角开始，按顺时针顺序依次为0，1，2，3
     * @param radius        圆角半径,不能小于0
     * @param refreshImmediately   是否立即更新
     */
    public void setRadius(int index, float radius, boolean refreshImmediately) {
        if (radius < 0) {
            return;
        }

        if (index == ALL_INDEX) {
            for (int i = 0; i < radii.length; i++) {
                radii[i] = radius;
            }
        } else if (index >=LEFT_TOP_INDEX && index <= LEFT_BOTTOM_INDEX) {
            radii[index * 2] = radius;
            radii[index * 2 + 1] = radius;
        }
        if (refreshImmediately) {
            invalidate();
        }
    }

//    public void setRadius(int index, float radius) {
//        setRadius(index, radius, true);
//    }

    private void init() {
        mReady = true;

        if (mSetupPending) {
            setup();
            mSetupPending = false;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (getDrawable() == null) {
            return;
        }

        Path path = new Path();
        //顺时针方向
        path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), radii, Path.Direction.CW);
        canvas.drawPath(path, mBitmapPaint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        setup();
    }


    @Override
    public void setImageBitmap(Bitmap bm) {
        super.setImageBitmap(bm);
        mBitmap = bm;
        setup();
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        super.setImageDrawable(drawable);
        mBitmap = getBitmapFromDrawable(drawable);
        setup();
    }

    @Override
    public void setImageResource(int resId) {
        super.setImageResource(resId);
        mBitmap = getBitmapFromDrawable(getDrawable());
        setup();
    }

    @Override
    public void setImageURI(Uri uri) {
        super.setImageURI(uri);
        mBitmap = getBitmapFromDrawable(getDrawable());
        setup();
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        if (cf == mColorFilter) {
            return;
        }

        mColorFilter = cf;
        mBitmapPaint.setColorFilter(mColorFilter);
        invalidate();
    }

    private Bitmap getBitmapFromDrawable(Drawable drawable) {
        if (drawable == null) {
            return null;
        }

        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        try {
            Bitmap bitmap;

            if (drawable instanceof ColorDrawable) {
                bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
            } else {
                bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
            }

            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
            return bitmap;
        } catch (OutOfMemoryError e) {
            return null;
        }
    }

    private void setup() {
        if (!mReady) {
            mSetupPending = true;
            return;
        }

        if (mBitmap == null) {
            return;
        }

        mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

        mBitmapPaint.setAntiAlias(true);
        mBitmapPaint.setShader(mBitmapShader);


        mBitmapHeight = mBitmap.getHeight();
        mBitmapWidth = mBitmap.getWidth();

        mDrawableRect.set(0, 0, getWidth(), getHeight());

        updateShaderMatrix();
        invalidate();
    }

    private void updateShaderMatrix() {
        float scale;
        float dx = 0;
        float dy = 0;

        mShaderMatrix.set(null);

        if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
            scale = mDrawableRect.height() / (float) mBitmapHeight;
            dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
        } else {
            scale = mDrawableRect.width() / (float) mBitmapWidth;
            dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
        }

        mShaderMatrix.setScale(scale, scale);
        mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);

        mBitmapShader.setLocalMatrix(mShaderMatrix);
    }

}